package main

import (
	"BilibiliConvertGo/util"
	"encoding/json"
	"io/fs"
	"os"
	"path/filepath"
	"strings"
)

type VideoInfo struct {
	title      string
	sourcePath string
	videoPath  string
	audioPath  string
	part       string
	page       int
	fromPC     bool
}

type EntryPC struct {
	GroupTitle string `json:"groupTitle"`
	Title      string `json:"title"`
	P          int    `json:"p"`
}

type Entry struct {
	Title    string   `json:"title"`
	PageData PageData `json:"page_data"`
}

type PageData struct {
	Part string `json:"part"`
	Page int    `json:"page"`
}

// 解析文件夹中的视频
func getVideoInfos(rootPath string) []VideoInfo {
	var res []VideoInfo

	// 判断目录是否不存在，不存在则报错返回
	_, err := os.Stat(rootPath)
	if err != nil {
		return res
	}

	// 缓存路径
	var temp []string
	err2 := filepath.Walk(rootPath, func(path string, info fs.FileInfo, err error) error {
		if strings.Index(path, "entry.json") != -1 || strings.Index(path, ".videoInfo") != -1 {
			lastIndex := strings.LastIndex(path, string(filepath.Separator))
			if lastIndex != -1 {
				temp = append(temp, path[:lastIndex])
			}
		}
		return err
	})
	if err2 != nil {
		return res
	}
	temp = util.RemoveRepeatedElement(temp)

	// 视频所在的路径
	var videoPath []string
	for i := range temp {
		if checkIsBilibiliVideo(temp[i]) {
			videoPath = append(videoPath, temp[i])
		}
	}

	for i := range videoPath {
		isMobile := false
		err := filepath.Walk(videoPath[i], func(path string, info fs.FileInfo, err error) error {
			if strings.Index(path, "entry.json") != -1 {
				isMobile = true
			}
			return err
		})
		if err != nil {
			continue
		}
		tempVideoInfo := VideoInfo{}
		if isMobile {
			tempVideoInfo = resolveMobileVideoInfo(videoPath[i])
		} else {
			tempVideoInfo = resolvePCVideoInfo(videoPath[i])
		}
		tempVideoInfo.sourcePath = videoPath[i]
		res = append(res, tempVideoInfo)
	}
	return res
}

// 检测目录是否为b站缓存的所在目录
func checkIsBilibiliVideo(path string) bool {
	cnt := 0
	err := filepath.Walk(path, func(path string, info fs.FileInfo, err error) error {
		if strings.Index(path, "entry.json") != -1 {
			cnt++
		}
		if strings.Index(path, ".m4s") != -1 {
			cnt++
		}
		if strings.Index(path, ".videoInfo") != -1 {
			cnt++
		}
		return err
	})
	if cnt == 3 {
		return true
	}
	if err != nil {
		return false
	}
	return false
}

// 解析手机端的缓存视频
func resolveMobileVideoInfo(sourcePath string) VideoInfo {
	res := VideoInfo{}
	err := filepath.Walk(sourcePath, func(path string, info fs.FileInfo, err error) error {
		if strings.Index(path, "entry.json") != -1 {
			var entry Entry
			file, _ := os.ReadFile(path)
			_ = json.Unmarshal(file, &entry)
			res.title = removeSpecialChar(entry.Title)
			res.part = removeSpecialChar(entry.PageData.Part)
			res.page = entry.PageData.Page
		}
		if strings.Index(path, "audio.m4s") != -1 {
			res.audioPath = path
		}
		if strings.Index(path, "video.m4s") != -1 {
			res.videoPath = path
		}
		return err
	})
	if err != nil {
		return res
	}
	return res
}

// 解析PC端的缓存视频
func resolvePCVideoInfo(sourcePath string) VideoInfo {
	res := VideoInfo{}
	flag := true
	err := filepath.Walk(sourcePath, func(path string, info fs.FileInfo, err error) error {
		if strings.Index(path, ".videoInfo") != -1 {
			var entry EntryPC
			file, _ := os.ReadFile(path)
			_ = json.Unmarshal(file, &entry)
			res.title = removeSpecialChar(entry.GroupTitle)
			res.part = removeSpecialChar(entry.Title)
			res.page = entry.P
		}
		res.fromPC = true
		if strings.Index(path, ".m4s") != -1 {
			if flag {
				res.audioPath = path
				flag = false
			} else {
				res.videoPath = path
			}
		}
		return err
	})
	if err != nil {
		return res
	}
	// 初步判断是否有30280.m4s文件，该文件一般为音频文件
	if strings.Index(res.videoPath, "30280.m4s") != -1 || strings.Index(res.audioPath, "30280.m4s") != -1 {
		// 其中有30280的文件，则判断是不是赋值反了
		if strings.Index(res.videoPath, "30280.m4s") != -1 {
			if strings.Index(res.audioPath, "30280.m4s") == -1 {
				// 调换video和audio
				temp := res.audioPath + ""
				res.audioPath = res.videoPath
				res.videoPath = temp
				return res
			} else {
				// 二者都有30280文件，则需要进行文件大小比对
				size1 := util.GetFileSize(res.videoPath)
				size2 := util.GetFileSize(res.audioPath)
				// 如果audio文件比video文件大，则说明反了
				if size2 > size1 {
					// 调换video和audio
					temp := res.audioPath + ""
					res.audioPath = res.videoPath
					res.videoPath = temp
					return res
				}
			}
		}
	} else {
		// 没有30280文件，则需要进行文件大小比对
		size1 := util.GetFileSize(res.videoPath)
		size2 := util.GetFileSize(res.audioPath)
		// 如果audio文件比video文件大，则说明反了
		if size2 > size1 {
			// 调换video和audio
			temp := res.audioPath + ""
			res.audioPath = res.videoPath
			res.videoPath = temp
			return res
		}
	}
	return res
}

// 移除影响程序运行的特殊字符
func removeSpecialChar(input string) string {
	input = strings.ReplaceAll(input, " ", "")
	input = strings.ReplaceAll(input, "|", "")
	input = strings.ReplaceAll(input, ">", "")
	input = strings.ReplaceAll(input, "<", "")
	input = strings.ReplaceAll(input, "\"", "")
	input = strings.ReplaceAll(input, "?", "")
	input = strings.ReplaceAll(input, "*", "")
	input = strings.ReplaceAll(input, ":", "")
	input = strings.ReplaceAll(input, "/", "")
	input = strings.ReplaceAll(input, "\\", "")
	input = strings.ReplaceAll(input, "&", "")
	input = strings.ReplaceAll(input, "\a", "")
	input = strings.ReplaceAll(input, "\b", "")
	input = strings.ReplaceAll(input, "\f", "")
	input = strings.ReplaceAll(input, "\n", "")
	input = strings.ReplaceAll(input, "\r", "")
	input = strings.ReplaceAll(input, "\t", "")
	input = strings.ReplaceAll(input, "\v", "")
	input = strings.ReplaceAll(input, ".", "")
	input = strings.ReplaceAll(input, ",", "")
	input = strings.ReplaceAll(input, "'", "")
	input = strings.ReplaceAll(input, "^", "")
	input = strings.ReplaceAll(input, "!", "")
	return input
}
